home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
libs
/
knowhow4
/
s_var.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-28
|
9KB
|
328 lines
#include "s_var.h"
inline long abs(long x)
{
return x<0 ? -x+1 : x;
}
////////////////////
Var_Table::Var_Table()
{
if((memory = new char[MEMORY_STEP]) == NULL)
{
kh_error_code = KH_MEMORY_ERROR;
memory = NULL;
adresses = NULL;
types = NULL;
return;
}
if((adresses = new long[ADRESS_STEP]) == NULL)
{
kh_error_code = KH_MEMORY_ERROR;
delete memory;
memory = NULL;
adresses = NULL;
types = NULL;
return;
}
if((types = new int[ADRESS_STEP]) == NULL)
{
kh_error_code = KH_MEMORY_ERROR;
delete memory;
delete adresses;
memory = NULL;
adresses = NULL;
types = NULL;
return;
}
memory_size = MEMORY_STEP;
memory_used = 0;
size = ADRESS_STEP;
used = 0;
marked = 0;
mem_marked = 0;
memset(memory, 0, memory_size);
memset(types, FREE, size);
memset(adresses, 0, P * size); // sizeof POINTER in LARGE model == 4 BYTES
}
/////////////////////////////////
Var_Table::~Var_Table()
{
for(; used > 0; used--)
{
delete remove(used - 1, OFF);
}
delete memory;
delete adresses;
delete types;
}
/////////////////////////////////
int Var_Table::get_type(int n)
{
int t = types[n];
if(t >= 0) // Not pointers
type = size_of = t;
else if(t < -USER_TYPE) // Array in memory
{ type = t; size_of = -(t + USER_TYPE); }
else
{ type = P; size_of = t; } // Array in heap
if(adresses[n] < 0)
type = FREE;
return type;
}
//////////////////////////////////
int Var_Table::get_size(int n)
{
int t = types[n];
if(t >= 0) // Not pointers
return t;
else if(t < -USER_TYPE) // Array in memory
return n == used - 1 ? memory_used - abs(adresses[n])
: abs(adresses[n + 1]) - abs(adresses[n]);
else
return P; // Array in heap
}
//////////////////////////////////
void* Var_Table::remove(int n, bool check)
{
if(adresses[n] < 0 || n >= used )
return NULL;
mem_marked += get_size(n);
void* ret = NULL;
if(types[n] > -USER_TYPE && types[n] < 0) // Pointer to heap
(long*)ret = (long*)(((long*)(memory + adresses[n]))[0]);
marked++;
adresses[n] = -adresses[n] - 1;
if(check)
check_memory_compress();
return ret;
}
/////////////////////////////////
long Var_Table::find(int n)
{
get_type(n);
return adresses[n];
}
/////////////////////////////////
int Var_Table::add(void* v, int t, int n, uint elems)
{
long addr; // Address of location in memory
int back = t; // Size of type or array
if(t < -USER_TYPE)
back = -(t + USER_TYPE) * elems;
else if(t < 0)
back = P;
if(types[n] != t || n == -1 // Incomp. types or add to the end
|| n == used // Direct write to the end
|| (t < -USER_TYPE && elems > get_size(n))) // Array
{
n = used++;
addr = memory_used;
memory_used += back;
if(!check_memory_expand()) // Not enought memory
{
used--;
memory_used -= back;
return -1;
}
}
else
addr = adresses[n]; // Insert, not add
switch(t)
{
case C: memory[addr] = ((char*)v)[0]; break; // char
case I: ((int*)(memory + addr))[0] = ((int*)v)[0]; break; // int
case L: ((long*)(memory + addr))[0] = ((long*)v)[0]; break; // long
case D: ((double*)(memory + addr))[0] = ((double*)v)[0]; break; // double
case PC: case PI: case PL: case PD: // Array in memory
memcpy(memory + addr, (char*)v, back);
break;
default:
((long*)(memory + addr))[0] = (long)(v);
break;
}
adresses[n] = addr; types[n] = t;
if(n != used - 1 && // Array copied over prev. array and free space find
(t < -USER_TYPE && elems > abs(adresses[n + 1]) - abs(adresses[n])))
{
types[used] = t; // Mark-to-remove
adresses[used++] = (long)(memory + addr + back);
}
return n;
}
/////////////////////////////////
int Var_Table::check_memory_expand()
{
int* t = types;
long* l = adresses;
char* c = memory;
if(size <= used)
{
if((types = (int*)realloc((int*)types,
(size = (used / ADRESS_STEP + 1) * ADRESS_STEP) * sizeof(int)))
== NULL)
{
size -= ADRESS_STEP;
types = t;
return 0;
}
if((adresses = (long*)realloc((long*)adresses,
size * sizeof(long))) == NULL)
{
delete types;
types = t;
adresses = l;
return 0;
}
}
if(memory_size <= memory_used)
{
if((memory = (char*)realloc((char*)memory,
(memory_size = (memory_used / MEMORY_STEP + 1) * MEMORY_STEP)
* sizeof(char))) == NULL)
{
memory = c;
return 0;
}
}
return 1;
}
/////////////////////////////
int Var_Table::check_memory_compress()
{
// if(used / 2 < marked || memory_used / 2 < mem_marked
// || used == size || memory_used == memory_size)
return memory_compress();
// return 0;
}
/////////////////////////////
int Var_Table::memory_compress()
{
int removed = 0;
long shift = 0;
long addr;
for(int i = 0; i < used; i++)
{
if((addr = adresses[i + removed]) < 0)
addr = -addr - 1;
addr -= shift;
while(adresses[i + removed] < 0 && i + removed < used)
{
shift += get_size(i + removed);
removed++;
}
if(i + removed == used)
break;
int sz = get_size(i + removed);
memmove(memory + addr, memory + addr + shift, sz);
int sign = adresses[i + removed] < 0 ? -1 : 1;
adresses[i] = sign * (abs(adresses[i + removed]) - shift);
types[i] = types[i + removed];
}
memory_used -= shift;
used -= removed;
if(size - used > ADRESS_STEP)
{
size = (size / used + 1) * ADRESS_STEP;
adresses = (long*)realloc((long*)adresses, size * sizeof(long));
types = (int*)realloc((int*)types, size * sizeof(int));
}
marked = 0;
mem_marked = 0;
return removed;
}
/////////////////////////////////// Demo code ///////////////////////////////
#include <iostream.h>
class Demo : public Var_Table
{
public:
void report();
};
void Demo::report()
{
cout << "\r\n";
for(int i = 0; i < used; i++)
{
int type = types[i];
cout << "i: " << i << ", type: ";
switch(type)
{
case C: cout << "C"; break;
case I: cout << "I"; break;
case L: cout << "L"; break;
case D: cout << "D"; break;
case PC: cout << "PC"; break;
case PI: cout << "PI"; break;
case PL: cout << "PL"; break;
case PD: cout << "PD"; break;
default: cout << "pointer"; break;
}
int sz = type > 0 ? type : (type < -USER_TYPE ? -type : P);
cout << ", (elem.) size: " << sz << ", value: ";
if(adresses[i] < 0)
cout << "FREE";
else
switch(type)
{
case C: cout << ((char*)(memory + adresses[i]))[0]; break;
case I: cout << ((int*)(memory + adresses[i]))[0]; break;
case L: cout << ((long*)(memory + adresses[i]))[0]; break;
case D: cout << ((double*)(memory + adresses[i]))[0]; break;
case PC: cout << memory + adresses[i]; break;
default: cout << "POINTER"; break;
}
cout << "\r\n";
}
cout << "---------------------------------------------\r\n";
cout << "used: " << used << ", mem. used: " << memory_used << "\r\n";
}
void main()
{
Demo* v = new Demo();
char c = 'Y';
int i = 3;
long l = 12;
double d = 2.5;
char* s = strdup("Hello"); // Never use stack strings
char* pc = "KNOW-HOW.SLANG 5.0";
// int* pi = &i; // ERROR! Destructor will call "delete" for i
// >>>>>>>>> add() check code and alloc/realloc of memory <<<<<<<<<<<<<<<
v->add(&c, C); // char
v->add(s, -C); // char* in heap
v->add(&i, I); // int
v->add(&l, L); // long
v->add(&d, D); // double
v->add(pc, PC, -1, strlen(pc) + 1); // Array in memory
v->report();
// >>>>>>>>> remove() check code and alloc/realloc of memory <<<<<<<<<<<<<<<
delete v->remove(0, OFF); // char, no compress
v->report();
delete v->remove(5, OFF);
v->report();
delete v->remove(1,OFF); // pointer, compress
v->report();
v->memory_compress();
v->report();
delete v->remove(2); // int, compress
v->report();
delete v->remove(1); // long, compress
v->report();
delete v;
}
//////////////////////////// End of Demo code ///////////////////////////////